#pragma once
#include <memory>
#include <unordered_map>
#include "StreamSocketChannel.h"
#include "XnccClient.h"
#include "XnccType.h"
namespace xncc {
namespace foundation {
    class Connector;
    using ConnectorPtr = std::shared_ptr<Connector>;
    class EventLoop;
    class XnccAddress;
    class StreamClient final : public XnccClient
    {
      public:
        StreamClient(EventLoop* loop, std::shared_ptr<XnccAddress> serverAddr);
        ~StreamClient() override;

        StreamClient(const StreamClient&)             = delete;
        StreamClient(const StreamClient&&)            = delete;
        StreamClient& operator=(const StreamClient&)  = delete;
        StreamClient& operator=(const StreamClient&&) = delete;

        void init() override;
        void connect() override;
        auto Type() const -> shared::XNCC_CLIENT_TYPE override { return shared::XNCC_CLIENT_TYPE::STREAM; }
        void disconnect();
        void stop();
        bool retry() const { return retry_; }

        void setWriteCompleteCallback(StreamSocketChannel::WriteCompleteCallback callack)
        {
            writeCompleteCallback_ = std::move(callack);
        }

      private:
        void newConnection(int sockfd);
        void removeConnection(types::connection_id_t connId, const std::string& reason);

        void handleIoMsg(const char* msg, uint32_t len, types::thread_id_t tid, types::connection_id_t connId);

        EventLoop*                                      loop_;
        ConnectorPtr                                    connector_;  // avoid revealing Connector
        StreamSocketChannel::WriteCompleteCallback      writeCompleteCallback_;
        bool                                            connect_;  // atomic
        std::shared_ptr<StreamSocketChannel>            serverChannel_;
        int                                             nextConnId_;
        const std::string                               serverAddrStr_;
        std::unordered_map<types::connection_id_t, int> connIdFd_;
    };
}  // namespace foundation
}  // namespace xncc